package com.gmics.unifiq;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;

import android.app.ProgressDialog;
import android.app.TimePickerDialog;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.text.InputType;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.SimpleAdapter;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import android.widget.TimePicker;
import android.widget.Toast;

import com.caldroid.CaldroidFragment;
import com.caldroid.CaldroidListener;
import com.gmics.android.R;
import com.gmics.unifiq.controller.AlertDialogManager;
import com.gmics.unifiq.controller.ConnectionDetector;
import com.gmics.unifiq.controller.EntityController;
import com.gmics.unifiq.controller.GPSTracker;
import com.gmics.unifiq.controller.GooglePlace;
import com.gmics.unifiq.controller.UserFunctions;
import com.gmics.unifiq.entity.Place;
import com.gmics.unifiq.entity.PlaceDetails;
import com.gmics.unifiq.entity.PlaceList;
import com.gmics.unifiq.entity.User;

public class Planner extends FragmentActivity {
	private EntityController controller = new EntityController();
	private EditText titleET, dateET, timeET, descET;
	private CaldroidFragment dialogCaldroidFragment;
	private Boolean isInternetPresent = false;
	private ConnectionDetector cd;
	private AlertDialogManager alert = new AlertDialogManager();
	private GooglePlace googlePlaces;
	private GPSTracker gps;
	private Button submitBtn;
	private ProgressDialog pDialog;
	private Spinner locationSpinner, locationTypeSpinner;
	private Bundle state;
	private int currentHour, currentMinute,
			creatorID, groupID;
	private Date selectedDate = null;
	private String locationRef = null, type, locationName = null;
	private RadioGroup locationRG;
	private RadioButton yesRB, noRB;
	private boolean nearby;
	private ImageButton mapBtn;
	private String[] locationTypeArr, locationTypeFormattedArr;
	private ArrayList<PlaceDetails> locationArr = new ArrayList<PlaceDetails>();
	private ArrayList<HashMap<String, String>> placesListItems = new ArrayList<HashMap<String, String>>();
	
	private static String SELECTED_LOCATION_TYPE = "school";
	public static String KEY_REFERENCE = "reference"; // id of the place
	public static String KEY_NAME = "name"; // name of the place
	public static String KEY_VICINITY = "vicinity"; // Place area name
	public static int VIEW_MAP_REQUEST_CODE = 1;
	public static int VIEW_MAP_RESULT_FAIL = 2;
	private static int MAX_DAYS = 30;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.planner_layout);

		Bundle bundle = getIntent().getExtras();
		UserFunctions uf = new UserFunctions();
		HashMap<String, String> user = uf.getUser(Planner.this);
		User tempUser = controller.retrieveUser(user.get("uid"));
		
		creatorID = Integer.valueOf(tempUser.getId());
		groupID = bundle.getInt("groupID");

		getWindow().setSoftInputMode(
				WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
		titleET = (EditText) findViewById(R.id.title_et);
		dateET = (EditText) findViewById(R.id.date_et);
		timeET = (EditText) findViewById(R.id.time_et);
		descET = (EditText) findViewById(R.id.desc_et);
		locationSpinner = (Spinner) findViewById(R.id.location_spinner);
		locationTypeSpinner = (Spinner) findViewById(R.id.location_type_spinner);
		locationRG = (RadioGroup) findViewById(R.id.location_rg);
		yesRB = (RadioButton) findViewById(R.id.yes_rb);
		noRB = (RadioButton) findViewById(R.id.no_rb);
		submitBtn = (Button) findViewById(R.id.submit_btn);
		mapBtn = (ImageButton) findViewById(R.id.map_icon);
		locationTypeArr = getResources().getStringArray(R.array.location_type);
		locationTypeFormattedArr = getResources().getStringArray(R.array.location_type_formatted);
		type = SELECTED_LOCATION_TYPE;
		
		yesRB.setChecked(true);
		type = null;
		nearby = true;

		state = savedInstanceState;
		cd = new ConnectionDetector(this);

		// Check if Internet present
		isInternetPresent = cd.isConnectingToInternet();
		if (!isInternetPresent) {
			// Internet Connection is not present
			alert.showAlertDialog(this, "Internet Connection Error",
					"Please connect to working Internet connection", false);
		}

		// creating GPS Class object
		gps = new GPSTracker(this);

		// check if GPS location can get
		if (gps.canGetLocation() && gps.getLatitude() != 0 && gps.getLongitude() != 0) {
			Log.d("Your Location", "latitude:" + gps.getLatitude()
					+ ", longitude: " + gps.getLongitude());
		} else {
			//Can't get user's current location
			alert.showAlertDialog(this, "GPS Status",
					"Please enable GPS to retrieve nearby locations.",
					false);
			onBackPressed();
		}

		googlePlaces = new GooglePlace();
		
		if (locationName == null){
			updateNearbyPlaces();
		}

		final CaldroidListener caldroidListener = new CaldroidListener() {

			@Override
			public void onChangeMonth(int month, int year) {
			}

			@Override
			public void onSelectDate(Date date, View view) {				
				Date currentDate = EntityController.dateTimeToDate(Calendar.getInstance().getTime());
				long diffDays = (date.getTime() - currentDate.getTime()) / (24 * 60 * 60 * 1000);
				
				if (EntityController.dateTimeToDate(date).compareTo(currentDate) < 0){
					Toast.makeText(Planner.this, "Selected date has passed. Please choose a valid date.",
							Toast.LENGTH_LONG).show();
				}
				else if (diffDays > MAX_DAYS){
					Toast.makeText(Planner.this, "Date is set too far into the future. Please set within a month.",
							Toast.LENGTH_LONG).show();
				}
				else{
					selectedDate = date;
					dateET.setText(EntityController.convertDateTimeToString(date));
					dialogCaldroidFragment.dismiss();
				}
			}
		};

		dateET.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				dialogCaldroidFragment = new CaldroidFragment();
				dialogCaldroidFragment.setCaldroidListener(caldroidListener);

				// If activity is recovered from rotation
				final String dialogTag = "CALDROID_DIALOG_FRAGMENT";
				if (state != null) {
					dialogCaldroidFragment.restoreDialogStatesFromKey(
							getSupportFragmentManager(), state,
							"DIALOG_CALDROID_SAVED_STATE", dialogTag);
					Bundle args = dialogCaldroidFragment.getArguments();
					if (args == null) {
						args = new Bundle();
						dialogCaldroidFragment.setArguments(args);
					}
					args.putString(CaldroidFragment.DIALOG_TITLE,
							"Select a date");
				} else {
					// Setup arguments
					Bundle bundle = new Bundle();
					// Setup dialogTitle
					bundle.putString(CaldroidFragment.DIALOG_TITLE,
							"Select a date");
					dialogCaldroidFragment.setArguments(bundle);
				}

				dialogCaldroidFragment.show(getSupportFragmentManager(),
						dialogTag);
			}

		});

		timeET.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				Calendar c = Calendar.getInstance();
				currentHour = c.get(Calendar.HOUR_OF_DAY);
				currentMinute = c.get(Calendar.MINUTE);

				TimePickerDialog.OnTimeSetListener timePickerListener = new TimePickerDialog.OnTimeSetListener() {
					@Override
					public void onTimeSet(TimePicker view, int selectedHour,
							int selectedMinute) {
						
						String time = new String();
						if (selectedHour < 10){
							time = "0" + String.valueOf(selectedHour) + ":";
						}
						else{
							time = String.valueOf(selectedHour) + ":";
						}
						
						if (selectedMinute < 10){
							time += "0" + String.valueOf(selectedMinute);
						}
						else{
							time += String.valueOf(selectedMinute);
						}
						
						timeET.setText(time);
					}
				};

				TimePickerDialog tpd = new TimePickerDialog(Planner.this,
						timePickerListener, currentHour, currentMinute, false);
				tpd.show();

			}

		});

		descET.setInputType(InputType.TYPE_NULL);

		descET.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				// TODO Auto-generated method stub
				descET.setInputType(InputType.TYPE_CLASS_TEXT);
				return false;
			}
		});

		ArrayAdapter<CharSequence> locationTypeAdapter = new ArrayAdapter<CharSequence>(
				Planner.this, android.R.layout.simple_spinner_dropdown_item,
				locationTypeFormattedArr);
		locationTypeSpinner.setAdapter(locationTypeAdapter);

		int locationTypePos = 0;
		while (!locationTypeFormattedArr[locationTypePos].equals(SELECTED_LOCATION_TYPE)){
			locationTypePos++;
		}
		
		locationTypeSpinner.setSelection(locationTypePos);
		
		locationTypeSpinner
				.setOnItemSelectedListener(new OnItemSelectedListener() {

					@Override
					public void onItemSelected(AdapterView<?> arg0, View arg1,
							int pos, long id) {
						// TODO Auto-generated method stub
						type = locationTypeArr[pos];
						updateNearbyPlaces();
					}

					@Override
					public void onNothingSelected(AdapterView<?> arg0) {
						// TODO Auto-generated method stub

					}

				});

		locationRG.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(RadioGroup arg0, int arg1) {
				// TODO Auto-generated method stub
				if (yesRB.isChecked()) {
					nearby = true;
				} else if (noRB.isChecked()) {
					nearby = false;
				}

				updateNearbyPlaces();
			}

		});
		
		mapBtn.setOnClickListener(new OnClickListener(){

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				Intent mapScreen = new Intent(Planner.this, ViewMap.class);
				mapScreen.putExtra("locationRef", locationRef);
				
    			if (locationArr.size() > 0 && placesListItems.size() > 0){
    				Bundle b = new Bundle();
    				b.putSerializable("locationArr", locationArr);
    				b.putSerializable("placesListItems", placesListItems);
    				mapScreen.putExtras(b);
    			}
    			
				startActivityForResult(mapScreen, VIEW_MAP_REQUEST_CODE);
			}
			
		});

		submitBtn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				String name = titleET.getText().toString();
				String desc = descET.getText().toString();
				String time = timeET.getText().toString();

				boolean valid = true;
				String msg = "";
				if (name.equals("")) {
					msg = "Please enter an event title";
					valid = false;
				} 
				else if (selectedDate == null){
					msg = "Please select a date";
					valid = false;
				}
				else if (time.equals("")){
					msg = "Please select a time";
					valid = false;
				}

				if (!valid){
					Toast.makeText(Planner.this, msg,
							Toast.LENGTH_LONG).show();
				}				
				else {
					
					boolean success = controller.createEvent(creatorID, name,
							selectedDate, time, groupID, locationRef, desc);

					if (success) {
						Toast.makeText(Planner.this,
								"Event successfully created!",
								Toast.LENGTH_LONG).show();
						Intent eventScreen = new Intent(Planner.this,
								ViewEvent.class);
						startActivity(eventScreen);
						finish();
					} else {
						Toast.makeText(
								Planner.this,
								"Event not successfully created. Please try again.",
								Toast.LENGTH_LONG).show();
					}
				}
			}

		});

	}

    private void updateNearbyPlaces() {
		PlaceList placeList = new PlaceList();
		ArrayList<PlaceDetails> placeArr = new ArrayList<PlaceDetails>();
		
		try {
			double radius = 0;
			double lat = 0, lng = 0;

			if (nearby) {
				lat = gps.getLatitude();
				lng = gps.getLongitude();
				placeList = googlePlaces.search(lat, lng, type);
			} else {
				placeList = googlePlaces.radarSearch(new String[] {type});
    			for (Place p : placeList.results) {
    				placeArr.add(googlePlaces.getPlaceDetails(p.reference));
    			}
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		ArrayList<HashMap<String, String>> placesListItems = new ArrayList<HashMap<String, String>>();
		String status = placeList.status;

		if (status.equals("OK")) {
			if (placeList.results != null) {
				if (nearby){
					for (Place p : placeList.results) {
						HashMap<String, String> map = new HashMap<String, String>();
	
						map.put(KEY_REFERENCE, p.reference);
						map.put(KEY_NAME, p.name);
	
						placesListItems.add(map);
					}
				}
				else{
	    			for (int i = 0; i < placeArr.size(); i++){
						HashMap<String, String> map = new HashMap<String, String>();
	
						map.put(KEY_REFERENCE, placeArr.get(i).result.reference);
						map.put(KEY_NAME, placeArr.get(i).result.name);
	
						placesListItems.add(map);
	    			}
				}
				
				SpinnerAdapter adapter = new SimpleAdapter(this,
						placesListItems, R.layout.location_list_item,
						new String[] { KEY_REFERENCE, KEY_NAME }, new int[] {
								R.id.location_ref, R.id.location_tv });

				locationSpinner.setAdapter(adapter);

				locationSpinner
						.setOnItemSelectedListener(new OnItemSelectedListener() {

							@Override
							public void onItemSelected(AdapterView<?> arg0,
									View arg1, int arg2, long arg3) {
								// TODO Auto-generated method stub
								locationRef = ((TextView) findViewById(R.id.location_ref))
										.getText().toString();
							}

							@Override
							public void onNothingSelected(AdapterView<?> arg0) {
								// TODO Auto-generated method stub
								locationRef = ((TextView) findViewById(R.id.location_ref))
										.getText().toString();
							}

						});
			} else {
				ArrayAdapter<CharSequence> tempAdapter = new ArrayAdapter<CharSequence>(
						this, android.R.layout.simple_spinner_dropdown_item,
						new String[] { "No places found." });
				locationSpinner.setAdapter(tempAdapter);
			}
		} else if (status.equals("ZERO_RESULTS")) {
			String header, msg;

			if (type != null) {
				header = "Type of location";
				msg = "No " + type
						+ " could be found. Please select another type.";
			} else {
				header = "Nearby Places";
				msg = "No nearby places could be found. Please try again.";
			}
			alert.showAlertDialog(Planner.this, header, msg, false);
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data){
    	if (requestCode == VIEW_MAP_REQUEST_CODE){
    		if (resultCode == RESULT_OK){ 	        
    		   locationArr = (ArrayList<PlaceDetails>) data.getExtras().getSerializable("locationArr");
    		   placesListItems = (ArrayList<HashMap<String, String>>) data.getExtras().getSerializable("placesListItems");
    			
		       locationName = data.getStringExtra("locationName");
		       locationRef = data.getStringExtra("locationRef");
		       
				ArrayList<HashMap<String, String>> placesListItems = new ArrayList<HashMap<String, String>>();
				HashMap<String, String> map = new HashMap<String, String>();

				map.put(KEY_REFERENCE, locationRef);
				map.put(KEY_NAME, locationName);

				placesListItems.add(map);
						
				SpinnerAdapter adapter = new SimpleAdapter(this,
						placesListItems, R.layout.location_list_item,
						new String[] { KEY_REFERENCE, KEY_NAME }, new int[] {
								R.id.location_ref, R.id.location_tv });

				locationSpinner.setAdapter(adapter);
    		}
    	}
    }
}
